import { defineStore } from 'pinia';
import _ from 'lodash';
import {
	ComponentTreeHelper,
	ComponentTreeNodeTypeEnum
} from '@CIF/ComponentTemplate/componentTree';
import { RUNTIME_CFG_ENUM } from '@CIF/Runtime/Global/variable';
import StorageHelper from '@CIF/Runtime/Global/storage';

const usePrimaryStore = defineStore('primary', {
	state: () => {
		return {
			vueInstance: undefined,
			callbackpool: {
				// demo data
				// K1: {
				//   value: "1212", // data 中 aa 字段对应的值
				//   origin: aa, // 对应 data 中的字段
				//   originCpnt: cpntid,
				//   listener：[uuid]
				// },
			},
			selectedInstance: null,
			selectedCpntTreeNodeInfo: [],
			activeCpntIdArr: [],
			activeEngineType: '',
			rendererCanvasSize: {
				width: '100vw',
				height: '100vh'
			},
			leftPanelVisible: true,
			rightPanelVisible: true,
			isFullScreen: false,
			dragMode: false,
			containerHeight: 0,
			containerWidth: 0,
			cpntTree: [],
			isTree: false,
			tempUploadProgressList: {},
			uploadProgressList: []
		};
	},
	getters: {
		getCpntTree: (state) => {
			return state.cpntTree;
		},
		getSelectedInstance: (state) => {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.Store:getSelectedInstance', state.selectedInstance);
			}
			return state.selectedInstance;
		},
		getContainerSize: (state) => {
			return {
				width: state.containerWidth,
				height: state.containerHeight
			};
		},
		getDragMode: (state) => {
			return state.dragMode;
		},
		getActiveEngineType: (state) => {
			return state.activeEngineType;
		},
		getSelectedCpntTreeNodeInfo: (state) => {
			return state.selectedCpntTreeNodeInfo;
		},
		// getSelectedInstanceConfiguration: (state) => {
		//   if (_.get(window, 'cif.config.logger.enable', false) === true) {
		//     console.log('CIF.Store:getSelectedInstanceConfiguration')
		//   }
		//   return _.get(state, 'selectedInstance.definitionRefrence.configuration')
		// },
		getActiveCpntIdArr: (state) => {
			return state.activeCpntIdArr;
		},

		/**
		 * CIF.R.R.ComponentContainer 提供默认 getDefaultCallbackData 方法，直接用
		 * @deprecated
		 * @param {*} state
		 * @returns
		 */
		// getCallbackPoolByKeys: (state) => (keys) => {
		// 	// let p = {}
		// 	// keys.forEach((key) => {
		// 	//   p[key] = state.callbackpool[key].value
		// 	// })
		// 	// return p
		// 	return {};
		// },
		/**
		 * 需要事先确保visitor对想要获取回调值的target进行了监听，否则将得到undefined
		 * @param {*} state
		 * @returns
		 */
		getCallbackValuesByTargets:
			(state) =>
			({ targets = [], visitor = '', data0 = false }) => {
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log('CIF.Store:getCallbackValuesByTargets', state);
				}
				const callbackValues = {};
				targets.forEach((target) => {
					const callback = _.get(state, `callbackpool.${target}`);
					if (_.isEmpty(callback)) {
						callbackValues[target] = undefined;
					}
					const listener = _.get(callback, 'listener', []);
					// 没进行显式监听，不允许获取回调池里的值
					if (listener.findIndex((ele) => _.isEqual(ele, visitor)) === -1) {
						callbackValues[target] = undefined;
					}
					let result = _.get(state, `callbackpool.${target}.value`);
					if (!result && data0) {
						const cpntTreeNode = ComponentTreeHelper.findTreeNodeQuick(callback.originCpnt);
						const instData = _.get(cpntTreeNode, 'componentInstance.data');
						if (!_.isArray(instData)) {
							return;
						}
						const defaultData = _.get(instData, '[0]');
						if (_.isNumber(defaultData) || _.isString(defaultData)) {
							callbackValues[target] = _.get(instData, `[${callback.origin}]`);
						} else {
							callbackValues[target] = _.get(defaultData, `${callback.origin}`);
						}
					} else {
						callbackValues[target] = result;
					}
				});
				return callbackValues;
			},
		getCallbackListeners: (state) => (target) => {
			return _.uniq(_.get(state, `callbackpool.${target}.listener`, []));
		},
		getRendererCanvasSize: (state) => {
			return _.get(state, `rendererCanvasSize`, {
				width: '100vw',
				height: '100vh'
			});
		},
		getLeftPanelVisible: (state) => {
			return state.leftPanelVisible;
		},
		getRightPanelVisible: (state) => {
			return state.rightPanelVisible;
		},
		getFullScreenState(state) {
			return state.isFullScreen;
		}
	},
	actions: {
		setUploadProgress(processInfo) {
			if (processInfo?.cdePercentage) {
				this.tempUploadProgressList = {
					...this.tempUploadProgressList,
					...processInfo.cdePercentage
				};
			}
			if (processInfo?.enginePercentage) {
				this.tempUploadProgressList[processInfo?.enginePercentage.key] =
					100 + Number(processInfo?.enginePercentage.percentage);
				if (Number(this.tempUploadProgressList[processInfo?.enginePercentage.key]) >= 199.9) {
					delete this.tempUploadProgressList[processInfo?.enginePercentage.key];
				}
			}
			this.uploadProgressList = Object.entries(this.tempUploadProgressList).map(([key, value]) => ({
				name: key.split('&')[0],
				percent: value / 2
			}));
			this.fileProgressCount = this.uploadProgressList.length + this.downloadProgressList.length;
		},
		updateTree(val) {
			this.$state.cpntTree = [];
			this.$state.isTree = false;
			// console.log('````````````this.$state.cpntTree ', this.$state.cpntTree);
			StorageHelper.set(RUNTIME_CFG_ENUM.APPLICATION_COMPONENT_TREE, val);
			setTimeout(() => {
				this.$state.cpntTree = val;
				this.$state.isTree = true;
			}, 300);
		},
		setContainerSize(size) {
			this.$state.containerWidth = size.offsetWidth;
			this.$state.containerHeight = size.offsetHeight;
		},
		setLeftPanelVisible(value) {
			this.$state.leftPanelVisible = value;
		},
		setRightPanelVisible(value) {
			this.$state.rightPanelVisible = value;
		},
		setFullScreenState(value) {
			this.$state.isFullScreen = value;
		},
		resetStore() {
			(this.$state.callbackpool = {}), (this.$state.selectedInstance = null);
			this.$state.activeCpntIdArr = [];
		},

		setSelectedInstance(instance) {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.Store:setSelectedInstance', instance);
			}
			this.$state.selectedInstance = instance;
		},

		setActiveEngineType(activeEngineType) {
			this.$state.activeEngineType = activeEngineType;
		},
		setSelectedCpntTreeNodeInfo(newTreeNodeInfo) {
			this.$state.selectedCpntTreeNodeInfo = newTreeNodeInfo;
			const newActiveCpntIdArr = newTreeNodeInfo
				.filter((x) => x.type !== ComponentTreeNodeTypeEnum.FOLDER)
				.map((x) => x.id);
			this.$state.activeCpntIdArr = newActiveCpntIdArr;
			if (newActiveCpntIdArr.length === 1) {
				const cpntTreeNode = ComponentTreeHelper.findTreeNodeQuick(newActiveCpntIdArr[0]);
				this.$state.selectedInstance = cpntTreeNode.componentInstance;
			} else {
				// TODO：多选模式配置
				this.$state.selectedInstance = null;
			}
		},
		setActiveCpntIdArr(newActiveCpntIdArr) {
			this.$state.activeCpntIdArr = newActiveCpntIdArr;
			if (newActiveCpntIdArr.length === 1) {
				const cpntTreeNode = ComponentTreeHelper.findTreeNodeQuick(newActiveCpntIdArr[0]);
				this.$state.selectedInstance = cpntTreeNode.componentInstance;
			} else {
				// TODO：多选模式配置
				this.$state.selectedInstance = null;
			}
		},
		serializationCallbackPool(instance) {
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.Store:serializationCallbackPool', instance);
				// console.log('state', this.$state);
			}
			// 将callbackpool相关字段初始化进store
			instance.callbackArgs.forEach((el) => {
				if (!this.$state.callbackpool[el.target]) {
					this.$state.callbackpool[el.target] = {
						origin: el.origin,
						originCpnt: instance.uuid
					};
				}
				if (!this.$state.callbackpool[el.target]['origin']) {
					this.$state.callbackpool[el.target]['origin'] = el.origin;
					this.$state.callbackpool[el.target]['originCpnt'] = instance.uuid;
				}
			});
			// TODO: 优化：拆分成不同的commit更清晰
			// 对过滤器引用到的回调进行监听
			// 配合监听器移除方式，需要允许添加相同监听器, getCallbackListeners 有做唯一过滤
			instance.filterCbVar.forEach((el) => {
				if (!_.get(this.$state, `callbackpool.${el}.listener`)) {
					_.set(this.$state, `callbackpool.${el}.listener`, []);
				}
				this.callbackpool[el]['listener'].push(instance.uuid);
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log('CIF.Store:serializationCallbackPool filterCbVar add listener');
				}
			});
			// 对过滤器引用到的回调进行监听
			// 配合监听器移除方式，需要允许添加相同监听器, getCallbackListeners 有做唯一过滤
			instance.fetcherCbVar.forEach((el) => {
				if (!_.get(this.$state, `callbackpool.${el}.listener`)) {
					_.set(this.$state, `callbackpool.${el}.listener`, []);
				}
				this.callbackpool[el]['listener'].push(instance.uuid);
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log('CIF.Store:serializationCallbackPool fetcherCbVar add listener');
				}
			});
			// 对组件配置引用到的回调进行监听
			// 配合监听器移除方式，需要允许添加相同监听器, getCallbackListeners 有做唯一过滤
			instance.callbackConfigPath.forEach((path) => {
				const target = _.get(instance.configData, path);
				if (!_.get(this.$state, `callbackpool.${target}.listener`)) {
					_.set(this.$state, `callbackpool.${target}.listener`, []);
				}
				this.callbackpool[target]['listener'].push(instance.uuid);
				if (_.get(window, 'cif.config.logger.enable', false) === true) {
					console.log(
						'CIF.Store:serializationCallbackPool callbackConfigPath add listener',
						target
					);
				}
			});
		},
		setCallBackArg({ origin, originCpnt, target }) {
			const oldCallback = this.$state.callbackpool[target];
			if (_.isEmpty(_.get(oldCallback, 'originCpnt'))) {
				// 此target未被占用
				// 若有旧的listener进行保留
				this.$state.callbackpool[target] = {
					origin: origin,
					originCpnt: originCpnt,
					listener: _.get(this.$state, `callbackpool.${target}.listener`, [])
				};
			}
		},
		unsetCallBackArg(target) {
			const oldCallback = this.$state.callbackpool[target];
			if (!_.isEmpty(oldCallback)) {
				oldCallback.origin = undefined;
				oldCallback.originCpnt = undefined;
			}
		},
		addCallBackListener({ listener, target }) {
			// 过滤器要加 listener, 回调组件也要加 listener
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.Store:addCallBackListener', listener, target);
			}
			const callback = this.$state.callbackpool[target];
			if (_.isEmpty(callback)) {
				this.$state.callbackpool[target] = {
					origin: undefined,
					originCpnt: undefined,
					listener: [listener]
				};
			} else {
				// const oldListener = _.get(state, `callbackpool.${target}.listener`, [])
				// if (_.isEmpty(oldListener.find((x) => _.isEqual(x, listener)))) {
				//   state.callbackpool[target].listener.push(listener)
				// }
				// 配合监听器移除方式，需要允许添加相同监听器, getCallbackListeners 有做唯一过滤
				if (_.isArray(this.$state.callbackpool[target].listener)) {
					this.$state.callbackpool[target].listener.push(listener);
				} else {
					this.$state.callbackpool[target].listener = [];
				}
			}
		},
		removeCallBackListener({ listener, target }) {
			// 移除listener
			if (_.get(window, 'cif.config.logger.enable', false) === true) {
				console.log('CIF.Store:removeCallBackListener', listener, target);
			}
			const callback = this.$state.callbackpool[target];
			if (!_.isEmpty(callback)) {
				const oldListener = _.get(callback, 'listener', []);
				// if (!_.isEmpty(oldListener.find((x) => _.isEqual(x, listener)))) {
				//   this.$state.callbackpool[target].listener = oldListener.filter((x) => !_.isEqual(x, listener))
				// }
				// 只删一个，因为可能存在同一个组件多次监听相同的target的情况
				if (!_.isArray(this.$state.callbackpool[target].listener)) {
					this.$state.callbackpool[target].listener.splice(oldListener.indexOf(listener), 1);
				}
			}
		},
		updateCallbackValue({ target, value }) {
			if (_.get(this.$state, `callbackpool.${target}.originCpnt`)) {
				_.set(this.$state, `callbackpool.${target}.value`, value);
			}
		},
		toggleDragMode() {
			this.$state.dragMode = !this.$state.dragMode;
		},
		setRendererCanvasSize(rendererCanvasSize) {
			this.$state.rendererCanvasSize = rendererCanvasSize;
		},
		updateCallbackPool({ target, origin, originCpnt, value }) {
			return new Promise((resolve) => {
				setTimeout(() => {
					const callback = this.$state.callbackpool[target];
					// 回调池中不存在指定target，说明没有设置好回调参数，因此不做处理
					if (!_.isEmpty(callback)) {
						// 对于回调池中已存在的target，需确认其原本是否由该组件设置的
						// 若非此target的暴露者，不允许设置target的值
						if (callback.origin == origin && callback.originCpnt == originCpnt) {
							if (_.get(window, 'cif.config.logger.enable', false) === true) {
								console.log('CIF.Store:updateCallbackPool', target);
							}
							this.updateCallbackValue({ target, value });
							resolve(true);
						}
						resolve(false);
					}
					resolve(false);
					resolve();
				}, 1000);
			});
		},

		changeCallbackPoolKey({ origin, originCpnt, oldTarget, newTarget }) {
			const newCallback = this.$state.callbackpool[newTarget];

			if (_.isEmpty(oldTarget)) {
				if (_.isEmpty(newTarget)) {
					// 新旧target都为空，啥也不干
					return true;
				}
				if (_.isEmpty(_.get(newCallback, 'originCpnt'))) {
					// 当前回调池里没这个回调, 执行新增逻辑
					this.setCallBackArg({
						target: newTarget,
						origin,
						originCpnt
					});
					return true;
				} else {
					// 回调池里有这个回调, 说明被占用了, 不作修改
					return false;
				}
			} else {
				// 旧callback非空的话，不移除旧的callback，
				if (!_.isEmpty(newTarget)) {
					if (_.isEqual(oldTarget, newTarget)) {
						// 新旧值一致，按兵不动
						return true;
					} else {
						// 新旧值不一致
						if (!_.isEmpty(_.get(newCallback, 'originCpnt'))) {
							// 回调池里有这个回调, 说明被占用了, 不作修改
							return false;
						} else {
							// 设置新的callback
							this.setCallBackArg({
								target: newTarget,
								origin,
								originCpnt
							});
							// 旧的origin、originCpnt和value置空
							this.unsetCallBackArg(oldTarget);
							return true;
						}
					}
				} else {
					this.unsetCallBackArg(oldTarget);
					return true;
				}
			}
		}
	}
});
export default usePrimaryStore;
